﻿using LxBasic;
using LxCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace LxCFD
{
    /// <summary>
    /// DHeadText.xaml 的交互逻辑
    /// </summary>
    public partial class DHeadData : UserControl
    {
        public DHeadData()
        {
            InitializeComponent();

        }
        public string Head
        {
            get { return (string)GetValue(HeadProperty); }
            set { SetValue(HeadProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Head.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeadProperty =
            DependencyProperty.Register("Head", typeof(string), typeof(DHeadData), new PropertyMetadata(""));

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register(nameof(Data), typeof(object), typeof(DHeadData),
                new FrameworkPropertyMetadata(null, new PropertyChangedCallback((d, e) => { (d as DHeadData).Convert(e.NewValue); })) { BindsTwoWayByDefault = true });



        public bool IsValid
        {
            get { return (bool)GetValue(IsValidProperty); }
            set { SetValue(IsValidProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HasError.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsValidProperty =
            DependencyProperty.Register(nameof(IsValid), typeof(bool), typeof(DHeadData), new PropertyMetadata(true));


        private void Convert(object v)
        {
            TextBox1.Text = v is null ? "null" : v.ToString();
        }
        private bool TryConvertBack(out object backObj, out string errMsg)
        {
            var str = this.TextBox1.Text;
            errMsg = null;
            switch (DataType)
            {
                case DataTypes.Undefined:
                case DataTypes.None:
                default:
                    backObj = str;
                    return true;
                case DataTypes.String:
                    backObj = str;
                    if (!string.IsNullOrEmpty(str))
                    {
                        return true;
                    }
                    else
                    {
                        errMsg = "不能为空";
                        return false;
                    }
                case DataTypes.Int:
                    if (int.TryParse(str, out int rint))
                    {
                        backObj = rint;
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为整数");
                        return false;
                    }
                case DataTypes.Double:
                    if (double.TryParse(str, out double rdouble))
                    {
                        backObj = rdouble;
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为数字");
                        return false;
                    }
                case DataTypes.Vector3d:
                    if (Vector3d.TryParse(str, out Vector3d rv))
                    {
                        backObj = rv;
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为Vector3d");
                        return false;
                    }
                case DataTypes.Field_Double:
                    if (double.TryParse(str, out double rdf))//这部分还要延伸
                    {
                        backObj = new ConstField.Double(rdf);
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为IField<double>");
                        return false;
                    }
                case DataTypes.Field_Vector3d:
                    if (Vector3d.TryParse(str, out Vector3d rvf))
                    {
                        backObj = new ConstField.Vector(rvf);
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为IField<Vector3d>");
                        return false;
                    }
                case DataTypes.ConstField_Double:
                    if (double.TryParse(str, out double rdp))//这部分还要延伸
                    {
                        backObj = new ConstField.Double(rdp);
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为IPara<double>");
                        return false;
                    }
                case DataTypes.ConstField_Vector3d:
                    if (Vector3d.TryParse(str, out Vector3d rvp))
                    {
                        backObj = new ConstField.Vector(rvp);
                        return true;
                    }
                    else
                    {
                        backObj = str;
                        errMsg = string.Format($"无法将“{str}”转为IPara<Vector3d>");
                        return false;
                    }
            }
        }

        private DataTypes _DataType = DataTypes.Undefined;
        public DataTypes DataType
        {
            get
            {
                if (_DataType != DataTypes.Undefined) { return _DataType; }
                Binding bind = BindingOperations.GetBinding(this, DataProperty);
                if (bind == null) { return _DataType; }
                string[] paths = bind.Path.Path.Split('.');
                object dataContext = this.DataContext;
                for (int i1 = 0; ; i1++)
                {
                    Type t = dataContext.GetType();
                    var p = t.GetProperty(paths[i1]);
                    if (i1 >= paths.Length - 1)
                    {
                        _DataType = calDataType(p.PropertyType);
                        return _DataType;
                    }
                    dataContext = p.GetValue(dataContext);
                    if (dataContext == null) { return _DataType; }
                }
            }
            set { _DataType = value; }
        }
        DataTypes calDataType(Type type)
        {
            if (type == null)
            {
                return DataTypes.Undefined;
            }
            else if (type == typeof(string))
            {
                return DataTypes.String;
            }
            else if (type == typeof(int))
            {
                return DataTypes.Int;
            }
            else if (type == typeof(double))
            {
                return DataTypes.Double;
            }
            else if (type == typeof(Vector3d))
            {
                return DataTypes.Vector3d;
            }
            else if (type == typeof(IField<double>) || type == typeof(FieldBase<double>))
            {
                return DataTypes.Field_Double;
            }
            else if (type == typeof(IField<Vector3d>) || type == typeof(FieldBase<Vector3d>))
            {
                return DataTypes.Field_Vector3d;
            }
            else if (type == typeof(ParameterBase<double>))
            {
                return DataTypes.ConstField_Double;
            }
            else if (type == typeof(ParameterBase<Vector3d>))
            {
                return DataTypes.ConstField_Vector3d;
            }
            throw new Exception("未知类型，待增加");
        }
        public enum DataTypes : byte
        {
            Undefined, None, String, Int, Double, Vector3d, ConstField_Double, ConstField_Vector3d, Field_Double, Field_Vector3d,
        }
        private void ConvertBack()
        {
            if (TryConvertBack(out object backObj, out string errMsg))
            {
                Data = backObj;
            }
            else
            {
                Convert(Data);
                LxLog.Warn($"{errMsg},已恢复原值");
            }
        }
        private void TextBox1_LostFocus(object sender, RoutedEventArgs e)
        {
            ConvertBack();
        }
        private void TextBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                ConvertBack();
            }
        }
        private void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
            IsValid = TryConvertBack(out object backObj, out string errMsg);
        }
    }

}
